package com.sne.common.util;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.sne.monitor.entity.MonitorTimeTask;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 任务执行工具
 * @author fanghh
 * @date 2020/12/11
 */
@UtilityClass
public class TaskInvokeUtil {


    /**
     * 执行方法
     * @param timeTask 系统任务
     */
    public void invokeMethod(MonitorTimeTask timeTask) throws Exception {
        String taskFun = timeTask.getTaskFun();
        String beanName = getBeanName(taskFun);
        String methodName = getMethodName(taskFun);
        List<Object[]> methodParams = getMethodParams(taskFun);
        invokeMethod(beanName,methodName,methodParams);
    }

    public void invokeMethod(String beanName,String methodName,List<Object[]> methodParams) throws Exception {
        Object bean = Class.forName(beanName).newInstance();
        if(CollectionUtils.isNotEmpty(methodParams)){
            Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
            method.invoke(bean,getMethodParamsValue(methodParams));
        }else {
            Method method = bean.getClass().getDeclaredMethod(methodName);
            method.invoke(bean);
        }

    }

    /**
     * 获取bean名称
     *
     * @param taskFun 目标字符串
     * @return bean名称
     */
    public String getBeanName(String taskFun)
    {
        String beanName = StringUtils.substringBefore(taskFun, "(");
        return StringUtils.substringBeforeLast(beanName, ".");
    }

    /**
     * 获取method方法参数相关列表
     * @param invokeTarget 目标字符串
     * @return String
     */
    public String getMethodName(String invokeTarget){
        String methodName = StringUtils.substringBefore(invokeTarget,"(");
        return StringUtils.substringAfterLast(methodName,".");
    }

    /**
     * 获取参数
     * @param invokeTarget 方法
     * @return List<Object[]>
     */
    public  List<Object[]> getMethodParams(String invokeTarget){
        String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
        if(StringUtils.isBlank(methodStr)){
            return null;
        }
        String[] params = methodStr.split(",");
        List<Object[]> classs = new LinkedList<>();
        for(String param:params){
            String str = StringUtils.trimToEmpty(param);
            if(StringUtils.contains(str,"'")){
                classs.add(new Object[]{StringUtils.
                        replace(str,"'",""),String.class});
            }else if(StringUtils.equalsIgnoreCase(str, "true") || StringUtils.equalsIgnoreCase(str, "false")){
                classs.add(new Object[]{Boolean.valueOf(str), Boolean.class});
            }else if(StringUtils.containsIgnoreCase(str,"L")){
                classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class });
            }else if (StringUtils.containsIgnoreCase(str, ".")){
                classs.add(new Object[] { new BigDecimal(str), BigDecimal.class });
            }else {
                classs.add(new Object[] { Integer.valueOf(str), Integer.class });
            }
        }
        return classs;
    }


    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    public  Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        List<? extends Class<?>> list = methodParams.stream().map(x -> (Class<?>) x[1]).collect(Collectors.toList());
        return list.toArray(classs);
    }

    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    public  Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] classs = new Object[methodParams.size()];
        List<Object> list = methodParams.stream().map(x -> (Object) x[0]).collect(Collectors.toList());
        return list.toArray(classs);
    }
}
